package com.cmc.cloud.cmclink.doc.service.impl;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.collection.CollectionUtil;
import com.alibaba.nacos.shaded.com.google.gson.Gson;
import com.baomidou.lock.annotation.Lock4j;
import com.cmc.cloud.cmclink.common.filter.FilterGroup;
import com.cmc.cloud.cmclink.common.filter.FilterRule;
import com.cmc.cloud.cmclink.doc.constants.errorconstant.LimitRuleItemErrorCodeConstants;
import com.cmc.cloud.cmclink.doc.entity.LimitRuleItemDO;
import com.cmc.cloud.cmclink.doc.enums.filter.FilterConditionFieldEnum;
import com.cmc.cloud.cmclink.doc.enums.filter.SiFilterConditionFieldEnum;
import com.cmc.cloud.cmclink.doc.mapper.LimitRuleItemMapper;
import com.cmc.cloud.cmclink.doc.rpcservice.CustomerRpcService;
import com.cmc.cloud.cmclink.doc.rpcservice.impl.*;
import com.cmc.cloud.cmclink.doc.service.LimitRuleItemService;
import com.cmc.cloud.cmclink.doc.vo.limitruleitemvo.*;
import com.cmes.framework.common.exception.util.ServiceExceptionUtil;
import com.cmes.framework.common.pojo.PageResult;
import com.cmes.framework.mybatis.core.query.LambdaQueryWrapperX;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.validation.annotation.Validated;

import javax.annotation.Resource;
import java.util.*;
import java.util.stream.Collectors;


/**
 * 禁接类明细信息 Service 实现类
 *
 * @author 招商轮船-管理员
 */
@Service
@Validated
public class LimitRuleItemServiceImpl implements LimitRuleItemService {

    public static final String COMMA = ",";

    @Resource
    private LimitRuleItemMapper limitRuleItemMapper;
    @Autowired
    private CustomerRpcService nameTransferService;

    private final Gson gson = new Gson();

    @Override
    @Transactional(rollbackFor = Exception.class)
    @Lock4j(name = "ruleItemUnique", keys = {"#createReqVO.getMainId", "#createReqVO.getMatchExpression.toString"})
    public void createLimitRuleItem(LimitRuleItemCreateReqVO createReqVO) {
        // 插入
        validateUniqueExists(createReqVO, null);
        LimitRuleItemDO limitRuleItem = BeanUtil.copyProperties(createReqVO, LimitRuleItemDO.class);
        limitRuleItem.setMatchExpression(gson.toJson(createReqVO.getMatchExpression()));
        limitRuleItemMapper.insert(limitRuleItem);
    }

    private void validateUniqueExists(LimitRuleItemBaseVO vo, Long id) {
        LambdaQueryWrapperX<LimitRuleItemDO> queryWrapperX = new LambdaQueryWrapperX<LimitRuleItemDO>()
                .eqIfPresent(LimitRuleItemDO::getMainId, vo.getMainId());
        if (id != null) {
            queryWrapperX.ne(LimitRuleItemDO::getId, id);
            queryWrapperX.eqIfPresent(LimitRuleItemDO::getMatchExpression, gson.toJson(vo.getMatchExpression()));
        }
        if (limitRuleItemMapper.selectCount(queryWrapperX) != 0L) {
            throw ServiceExceptionUtil.exception(LimitRuleItemErrorCodeConstants.LIMIT_RULE_ITEM_EXISTED);
        }
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    @Lock4j(name = "ruleItemUnique", keys = {"#updateReqVO.getMainId", "#updateReqVO.getMatchExpression.toString"})
    public void updateLimitRuleItem(LimitRuleItemUpdateReqVO updateReqVO) {
        // 校验存在
        validateLimitRuleItemExists(updateReqVO.getId());
        validateUniqueExists(updateReqVO, updateReqVO.getId());
        // 更新
        LimitRuleItemDO updateObj = BeanUtil.copyProperties(updateReqVO, LimitRuleItemDO.class);
        updateObj.setMatchExpression(gson.toJson(updateReqVO.getMatchExpression()));
        limitRuleItemMapper.updateById(updateObj);
    }

    @Override
    public void deleteLimitRuleItem(Long id) {
        // 校验存在
        validateLimitRuleItemExists(id);
        // 删除
        limitRuleItemMapper.deleteById(id);
    }

    private void validateLimitRuleItemExists(Long id) {
        if (limitRuleItemMapper.selectById(id) == null) {
            throw ServiceExceptionUtil.exception(LimitRuleItemErrorCodeConstants.LIMIT_RULE_ITEM_NOT_EXISTS);
        }
    }

    @Override
    public LimitRuleItemDO getLimitRuleItem(Long id) {
        return limitRuleItemMapper.selectById(id);
    }

    @Override
    public LimitRuleItemRespVO getLimitRuleItemByMainId(Long id) {
        LimitRuleItemDO ruleItemDO = limitRuleItemMapper.selectOne(new LambdaQueryWrapperX<LimitRuleItemDO>().eqIfPresent(LimitRuleItemDO::getMainId, id));
        if (ruleItemDO == null) {
            return new LimitRuleItemRespVO();
        }
        LimitRuleItemRespVO limitRuleItemRespVO = BeanUtil.copyProperties(ruleItemDO, LimitRuleItemRespVO.class, "matchExpression");
        limitRuleItemRespVO.setMatchExpression(gson.fromJson(ruleItemDO.getMatchExpression(), FilterGroup.class));

        List<String> bkpCodeValues = Optional.ofNullable(limitRuleItemRespVO).map(LimitRuleItemRespVO::getMatchExpression).map(FilterGroup::getFilterRules).orElse(Collections.emptyList())
                .stream().filter(f -> f != null && (FilterConditionFieldEnum.BKP_CODE.getFieldName().equals(f.getFieldName()) || SiFilterConditionFieldEnum.BKP_CODE.getFieldName().equals(f.getFieldName()))).map(FilterRule::getValue).collect(Collectors.toList());
        if (!CollectionUtil.isEmpty(bkpCodeValues)){
            ArrayList<String> strings = new ArrayList<>();
            bkpCodeValues.forEach(t -> {
                String[] split = t.split(COMMA);
                strings.addAll(Arrays.asList(split));
            });
            limitRuleItemRespVO.setBkpMap(nameTransferService.getCompanyNameMap(strings));
        }
        return limitRuleItemRespVO;
    }

    @Override
    public List<LimitRuleItemDO> getLimitRuleItemList(Collection<Long> ids) {
        return limitRuleItemMapper.selectBatchIds(ids);
    }

    @Override
    public PageResult<LimitRuleItemDO> getLimitRuleItemPage(LimitRuleItemPageReqVO reqVO) {
        LambdaQueryWrapperX<LimitRuleItemDO> queryWrapperX = new LambdaQueryWrapperX<>();
        queryWrapperX.likeIfPresent(LimitRuleItemDO::getMatchExpression, gson.toJson(reqVO.getMatchExpression()));
        return limitRuleItemMapper.selectPage(reqVO, queryWrapperX);
    }

    @Override
    public List<LimitRuleItemRespVO> getLimitRuleItemByMainIds(List<Long> ids) {
        List<LimitRuleItemRespVO> ruleItemList = new ArrayList<>();
        if (CollectionUtil.isEmpty(ids)) {
            return ruleItemList;
        }
        List<LimitRuleItemDO> tempList = limitRuleItemMapper.selectList(new LambdaQueryWrapperX<LimitRuleItemDO>().in(LimitRuleItemDO::getMainId, ids));
        if (CollectionUtil.isEmpty(tempList)) {
            return ruleItemList;
        }
        tempList.forEach(e -> {
            LimitRuleItemRespVO item = new LimitRuleItemRespVO();
            item.setMainId(e.getMainId());
            item.setMatchExpression(gson.fromJson(e.getMatchExpression(), FilterGroup.class));
            ruleItemList.add(item);
        });
        return ruleItemList;
    }
}
